//
//  Person.m
//  runtimeTest
//
//  Created by Song on 2018/4/17.
//  Copyright © 2018年 Song. All rights reserved.
//

#import "Person.h"

#import <objc/runtime.h>

@interface Person() <NSCoding>

@end

@implementation Person

// 不需要解档的属性
-(NSArray *)ignoredNames {
    return @[@"_aaa",@"_bbb",@"_ccc"];
}

// 解档方法：将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程（反序列化）
-(instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        
        unsigned int outCount = 0;
        Ivar *ivars = class_copyIvarList([self class], &outCount);
        
        for (int i = 0; i < outCount; i++) {
            Ivar ivar = ivars[i];
            // 将每个成员变量名转换为NSString对象类型
            NSString *strKey = [NSString stringWithUTF8String:ivar_getName(ivar)];
            
            // 忽略不需要解档的属性
            if ([[self ignoredNames] containsObject:strKey]) {
                continue;
            }
            
            id value = [aDecoder decodeObjectForKey:strKey]; // 根据变量名解档取值，无论是什么类型
            [self setValue:value forKey:strKey]; // 取出的值 设置给属性
        }
        free(ivars);
    }
    return self;
}

// 归档方法: 将数据结构或对象转换成二进制串的过程 (序列化)
-(void)encodeWithCoder:(NSCoder *)aCoder {
    unsigned int outCount = 0;
    Ivar *ivars = class_copyIvarList([self class], &outCount);
    
    for (int i = 0; i < outCount; i++) {
        Ivar ivar = ivars[i];
        // 将每个成员变量名转换为NSString对象类型
        NSString *strKey = [NSString stringWithUTF8String:ivar_getName(ivar)];
        
        // 忽略不需要归档的属性
        if ([[self ignoredNames] containsObject:strKey]) {
            continue;
        }
        
        id value = [self valueForKeyPath:strKey]; // 通过成员变量名，取出成员变量的值
        [self setValue:value forKey:strKey]; // 将值归档
    }
    free(ivars);
}

@end
